'use strict';

Object.defineProperty(exports, "__esModule", {
  value: true
});

var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };

var _isPromise = require('../utils/isPromise');

var _isPromise2 = _interopRequireDefault(_isPromise);

var _promiseCounter = require('./promiseCounter');

var _promiseCounter2 = _interopRequireDefault(_promiseCounter);

var _loading = require('../actions/loading');

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

function _showLoading(dispatch) {
  if (_promiseCounter2.default.isEmpty()) {
    dispatch((0, _loading.showLoading)());
  }

  _promiseCounter2.default.countUp();
}

function _hideLoading(dispatch) {
  // make sure the count down the PromiseCounter in another event loop
  // to handle we chain the ajax call.
  setTimeout(function () {
    _promiseCounter2.default.countDown();

    // if there is no promise, we relase the loading bar
    if (_promiseCounter2.default.isEmpty()) {
      dispatch((0, _loading.hideLoading)());
    }
  }, 0);
}

exports.default = function (_ref) {
  var dispatch = _ref.dispatch,
      getState = _ref.getState;
  return function (next) {
    return function (action) {
      // We wish all actions follow the FSA standard.
      // We will add strict FSA checking here in later time.
      if (!action.payload) {
        return next(action);
      }
      var promise = action.payload.promise || action.payload;
      if (!(0, _isPromise2.default)(promise)) {
        return next(action);
      }

      var ignoreLoadingbar = false;
      var handlers = null;

      if (action.meta) {
        ignoreLoadingbar = !!action.meta.ignoreLoadingbar;
        handlers = action.meta.handlers;
      }

      if (!ignoreLoadingbar) {
        _showLoading(dispatch);
      }

      var reportError = function reportError(error) {
        dispatch(_extends({}, action, {
          payload: error,
          error: true
        }));
        if (!ignoreLoadingbar) {
          _hideLoading(dispatch);
        }

        if (handlers) {
          if (handlers.failed) {
            handlers.failed(dispatch, getState, error);
          }

          if (handlers.finally) {
            handlers.finally(dispatch, getState, error);
          }
        }

        throw error;
      };

      return promise.then(function (result) {
        dispatch(_extends({}, action, {
          payload: result
        }));

        if (!ignoreLoadingbar) {
          _hideLoading(dispatch);
        }

        if (handlers) {
          if (handlers.success) {
            handlers.success(dispatch, getState, result);
          }

          if (handlers.finally) {
            handlers.finally(dispatch, getState, result);
          }
        }
      }, function (error) {
        reportError(error);
      }).catch(function (error) {
        reportError(error);
      });
    };
  };
};